iT邦幫忙

2024 iThome 鐵人賽

DAY 9
0
Software Development

我命由我不由語言 java爬蟲挑戰系列 第 9

java爬蟲挑戰 Day 9 - 使用Jsoup解析物件 (2)

  • 分享至 

  • xImage
  •  

今天目標是點擊租物列表的物件,進入頁面取得詳細資料。

將很多變數、函數都進行了重新命名,程式碼也改了很多,希望不會影響閱讀。

RentalCrawlerService 增加函數

調整了爬蟲Service,現在如下

public interface RentalCrawlerService {
    //取得最新的591租屋目錄資訊
    List<RentalCatalog> fetchLatestRentalCatalog();
    //取得591租屋詳細資訊
    RentalDetail fetchRentalDetail(RentalCatalog rentalCatalog);
}

StartupRunner 調整動作

現在爬蟲Service有兩個函數

  1. 取得最新的591租屋目錄資訊
  2. 取得591租屋詳細資訊

所以我們要取得所有的詳細資訊就是,點擊每個目錄,進去進行二次爬取資料。

@Override
public void run(ApplicationArguments args) throws Exception {
    List<RentalCatalog> list = rentalCrawlerService.fetchLatestRentalCatalog();
    list.stream().forEach(obj ->rentalCrawlerService.fetchRentalDetail(obj));
}

RentalCrawlerServiceImp 實作

因為兩隻函數都會用到爬蟲相關的方法,故移到初始化時進行。
程式結束時,再將driver關閉。

private WebDriver driver;
@PostConstruct
public void init() {
    webDriverInit();
    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
        driver.quit();
    }));
}

fetchRentalDetail的實作
就是使用連結,進行二次爬取。

@Override
public RentalDetail fetchRentalDetail(RentalCatalog rentalCatalog) {
    log.info("Starting to fetch rental detail data...");
    String detailUrl = rentalCatalog.getLink();
    Document doc = getJsoupDoc(detailUrl);
    RentalDetail rentalDetail = parseRentalDetail(doc);
    return rentalDetail;
}

最麻煩的其實就是解析資料。

一樣使用Jsoup的選擇器選取資料。

要注意的是,提供設備591是使用class取控制的。
https://ithelp.ithome.com.tw/upload/images/20240826/20168635oi9gZfO60U.png

https://ithelp.ithome.com.tw/upload/images/20240826/20168635lDHuyQBErA.png

這個是有陽台的

<dl class="" data-v-cfafc3c0="">
    <dt data-v-cfafc3c0="">
    <i class="ic-house house-balcony" data-v-cfafc3c0=""></i>
    </dt>
    <dd class="text" data-v-cfafc3c0="">2陽台</dd>
</dl>

這個是沒有陽台的


<dl class="del" data-v-cfafc3c0="">
    <dt data-v-cfafc3c0="">
    <i class="ic-house house-balcony" data-v-cfafc3c0=""></i>
    </dt>
    <dd class="text" data-v-cfafc3c0="">陽台</dd>
</dl>

差別在於
dl class="del" 跟 dl class="" 而已

知道條件後就可以寫出程式碼。

private RentalDetail parseRentalDetail(Document doc) {
    RentalDetail rentalDetail = new RentalDetail();
    // 租住說明
    String rentalDescription = doc.select("div.service-cate:has(i.icon-desc) span").text();
    rentalDetail.setRentalDescription(rentalDescription);
    // 房屋守則
    String houseRules = doc.select("div.service-cate:has(i.icon-rule) span").text();
    rentalDetail.setHouseRules(houseRules);
    // 設備列表
    rentalDetail.setHasFridge(!doc.select("dl:has(i.house-fridge-big)").hasClass("del"));
    rentalDetail.setHasWasher(!doc.select("dl:has(i.house-washer)").hasClass("del"));
    rentalDetail.setHasTv(!doc.select("dl:has(i.house-tv)").hasClass("del"));
    rentalDetail.setHasCold(!doc.select("dl:has(i.house-cold)").hasClass("del"));
    rentalDetail.setHasHeater(!doc.select("dl:has(i.house-heater)").hasClass("del"));
    rentalDetail.setHasBed(!doc.select("dl:has(i.house-bed)").hasClass("del"));
    rentalDetail.setHasCloset(!doc.select("dl:has(i.house-closet)").hasClass("del"));
    rentalDetail.setHasFourth(!doc.select("dl:has(i.house-fourth)").hasClass("del"));
    rentalDetail.setHasWifi(!doc.select("dl:has(i.house-wifi-big)").hasClass("del"));
    rentalDetail.setHasGas(!doc.select("dl:has(i.house-gas)").hasClass("del"));
    rentalDetail.setHasSofa(!doc.select("dl:has(i.house-sofa)").hasClass("del"));
    rentalDetail.setHasTable(!doc.select("dl:has(i.house-table)").hasClass("del"));
    rentalDetail.setHasBalcony(!doc.select("dl:has(i.house-balcony)").hasClass("del"));
    rentalDetail.setHasLift(!doc.select("dl:has(i.house-lift)").hasClass("del"));
    rentalDetail.setHasParking(!doc.select("dl:has(i.house-parking)").hasClass("del"));
    log.info(rentalDetail.getInfo());
    return rentalDetail;
}

RentalDetail

package tw.grass.rental_crawler.model;

import lombok.Data;

@Data
public class RentalDetail {
    String rentalDescription;
    String houseRules;
    String address;
    String price;
    String floorAndArea;
    boolean hasFridge;
    boolean hasWasher;
    boolean hasTv;
    boolean hasCold;
    boolean hasHeater;
    boolean hasBed;
    boolean hasCloset;
    boolean hasFourth;
    boolean hasWifi;
    boolean hasGas;
    boolean hasSofa;
    boolean hasTable;
    boolean hasBalcony;
    boolean hasLift;
    boolean hasParking;

}

git 狀態

https://ithelp.ithome.com.tw/upload/images/20240826/20168635SIB1p0TWVj.png

小結

現在我們已經爬取到我們要得租屋資訊了,但是目錄資訊那邊其實有分頁的問題要處理。
https://ithelp.ithome.com.tw/upload/images/20240826/20168635hqzzS4nKSk.png

不過明天應該會先建立資料庫,否則不知道哪些資料是新的還舊的。


上一篇
java爬蟲挑戰 Day 8 - 使用Jsoup解析物件 (1)
下一篇
java爬蟲挑戰 Day 10 - H2 資料庫 & JPA 引入
系列文
我命由我不由語言 java爬蟲挑戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言